/**
 * Generali Solutions d'assurances - Tous droits réservés &copy; 2007 - 2010
 */

package fr.generali.accueilclient.client.assembler.output;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import fr.generali.accueilclient.client.assembler.output.p44.DonneesContactP44Mapper;
import fr.generali.accueilclient.client.om.IAdresse;
import fr.generali.accueilclient.client.om.ICharte;
import fr.generali.accueilclient.client.om.IClientAssociation;
import fr.generali.accueilclient.client.om.IClientAutre;
import fr.generali.accueilclient.client.om.IClientCollectivite;
import fr.generali.accueilclient.client.om.IClientCopropriete;
import fr.generali.accueilclient.client.om.IClientEntreprise;
import fr.generali.accueilclient.client.om.IClientParticulier;
import fr.generali.accueilclient.client.om.IClientProfessionnel;
import fr.generali.accueilclient.client.om.ICoordonneeBancaire;
import fr.generali.accueilclient.client.om.IDonneeMarketing;
import fr.generali.accueilclient.client.om.IEmail;
import fr.generali.accueilclient.client.om.IEnvironnement;
import fr.generali.accueilclient.client.om.IIndicateursDemat;
import fr.generali.accueilclient.client.om.ILien;
import fr.generali.accueilclient.client.om.IPersonne;
import fr.generali.accueilclient.client.om.IPersonneMorale;
import fr.generali.accueilclient.client.om.IPersonnePhysique;
import fr.generali.accueilclient.client.om.IPieceIdentite;
import fr.generali.accueilclient.client.om.ISiteInternet;
import fr.generali.accueilclient.client.om.ITelephone;
import fr.generali.accueilclient.client.om.NaturePersonne;
import fr.generali.accueilclient.client.om.impl.Communication;
import fr.generali.accueilclient.client.om.impl.Environnement;
import fr.generali.accueilclient.client.om.impl.Lien;
import fr.generali.accueilclient.client.om.impl.PieceIdentite;
import fr.generali.refservcommuns.rce.demat.commundocument.dossierdocument.DtoDossierDocument;
import fr.generali.refservcommuns.rce.demat.consultpersonneenvcomplet.dossierpersonneenvcomplet.DtoDossierP44;
import fr.generali.refservcommuns.rce.demat.consultpersonneenvcomplet.dossierpersonneenvcomplet.DtoDossierSphereProfessionnelle;
import fr.generali.refservcommuns.rce.demat.servperscom.ctc.gestioncontacts.DtoDossierContact;
import fr.generali.refservcommuns.rce.demat.servperscom.ctc.gestioncontacts.DtoInformationCommunication;
import fr.generali.refservcommuns.rce.demat.servperscom.dct.gestiondocuments.DtoCharteAccompagnement;
import fr.generali.refservcommuns.rce.demat.servperscom.dct.gestiondocuments.DtoIdentifiantSecuriteSociale;
import fr.generali.refservcommuns.rce.demat.servperscom.dct.gestiondocuments.DtoPieceIdentite;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.AbstractDtoPersonne;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoIndicateurDematerialisation;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoPersonneMorale;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.personnes.DtoPersonnePhysique;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.profilmarketingpersonnes.DtoDonneesMarketing;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.profilmarketingpersonnes.DtoProfilMarketing;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.referencebancaire.DtoDossierCoordonneesBancaires;
import fr.generali.refservcommuns.rce.demat.servperscom.pty.relationspersonnes.DtoLienPersonnes;

/**
 * Transforme un {@link DtoDossierP44} en {@link IPersonne}
 * 
 * @author selrhazala
 */
@Component("dtoDossierP44ToPersonneConverter")
public class DtoDossierP44ToPersonneConverter implements Converter<DtoDossierP44, IPersonne> {

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(DtoDossierP44ToPersonneConverter.class);

    /**
     * Assembler de personne physique
     */
    @Autowired
    @Qualifier("dtoPersonnePhysique2PersonnePhysiqueP44Converter")
    private Converter<DtoPersonnePhysique, IPersonnePhysique> dtoPersonnePhysique2PersonnePhysiqueP44Converter;

    /**
     * Assembler de personne morale
     */
    @Autowired
    @Qualifier("dtoPersonneMorale2PersonneMoraleP44Converter")
    private Converter<DtoPersonneMorale, IPersonneMorale> dtoPersonneMorale2PersonneMoraleP44Converter;

    /**
     * Assembler pour un particulier
     */
    @Autowired
    @Qualifier("dtoDossierP44ToClientParticulierConverter")
    private Converter<DtoDossierP44, IClientParticulier> dtoDossierP44ToClientParticulierConverter;

    /**
     * Assembler pour un pro
     */
    @Autowired
    @Qualifier("dtoDossierP44ToClientProfessionnelConverter")
    private Converter<DtoDossierP44, IClientProfessionnel> dtoDossierP44ToClientProfessionnelConverter;

    /**
     * Assembler pour une association
     */
    @Autowired
    @Qualifier("dtoDossierP44ToClientAssociationConverter")
    private Converter<DtoDossierP44, IClientAssociation> dtoDossierP44ToClientAssociationConverter;

    /**
     * Assembler pour une collectivité
     */
    @Autowired
    @Qualifier("dtoDossierP44ToClientCollectiviteConverter")
    private Converter<DtoDossierP44, IClientCollectivite> dtoDossierP44ToClientCollectiviteConverter;

    /**
     * Assembler pour une copropriété
     */
    @Autowired
    @Qualifier("dtoDossierP44ToClientCoproprieteConverter")
    private Converter<DtoDossierP44, IClientCopropriete> dtoDossierP44ToClientCoproprieteConverter;

    /**
     * Assembler pour une entreprise
     */
    @Autowired
    @Qualifier("dtoDossierP44ToClientEntrepriseConverter")
    private Converter<DtoDossierP44, IClientEntreprise> dtoDossierP44ToClientEntrepriseConverter;

    /**
     * Assembler pour tout autre type de client
     */
    @Autowired
    @Qualifier("dtoDossierP44ToClientAutreConverter")
    private Converter<DtoDossierP44, IClientAutre> dtoDossierP44ToClientAutreConverter;

    /**
     * L'assembler de Charte Accompagnement
     */
    @Autowired
    @Qualifier("dtoCharteAccompagnement2CharteConverter")
    private Converter<DtoCharteAccompagnement, ICharte> dtoCharteAccompagnement2CharteConverter;

    /**
     * L'assembler de Piece d'Identite
     */
    @Autowired
    @Qualifier("dtoPieceIdentite2PieceIdentiteConverter")
    private Converter<DtoPieceIdentite, IPieceIdentite> dtoPieceIdentite2PieceIdentiteConverter;
    
    /**
     * L'assembler de Donnee Marketing
     */
    @Autowired
    @Qualifier("dtoDonneesMarketing2DonneeMarketingConverter")
    private Converter<List<DtoDonneesMarketing>, IDonneeMarketing> dtoDonneesMarketing2DonneeMarketingConverter;

    /**
     * Permet de mapper adresse, téléphone et email
     */
    @Autowired
    private DonneesContactP44Mapper donneesContactP44Mapper;

    /**
     * Permet de mapper le rib
     */
    @Autowired
    @Qualifier("dtoDossierCoordonneesBancaires2ListCoordonneeBancaireP44Converter")
    private Converter<List<DtoDossierCoordonneesBancaires>, List<ICoordonneeBancaire>> dtoDossierCoordonneesBancaires2ListCoordonneeBancaireP44Converter;

    /**
     * Mapping indicateurs demat
     */
    @Autowired
    @Qualifier("dtoIndicateurDematerialisation2IndicateurDematP44Converter")
    private Converter<List<DtoIndicateurDematerialisation>, IIndicateursDemat> dtoIndicateurDematerialisation2IndicateurDematP44Converter;

    /**
     * {@inheritDoc}
     */
    public IPersonne convert(DtoDossierP44 input) {
        LOGGER.debug("assemble");

        DtoPersonneMorale personneMorale = input.getPersonneMorale();
        DtoPersonnePhysique personnePhysique = input.getPersonnePhysique();
        boolean isPersonnePhysique = personneMorale == null && personnePhysique != null;
        boolean isPersonneMorale = personneMorale != null;
        NaturePersonne nature = calculerNature(personneMorale, personnePhysique, isPersonnePhysique, isPersonneMorale);

        IPersonne client = buildClient(input, nature);

        if (NaturePersonne.PARTICULIER.equals(nature) || NaturePersonne.PROFESSIONNEL.equals(nature)) {
            mapperPersonnePhysique(personnePhysique, client, input.getDossierCoordonneesBancaires(),
                            input.getDossierContact(), input.getDossierSphereProfessionnelle(),
                            input.getProfilMarketing(), input.getIndicateurMarketing());
        } else {
            mapperPersonneMorale(personneMorale, client, input.getDossierCoordonneesBancaires(),
                            input.getDossierContact(), input.getProfilMarketing());
        }

        if (client != null) {
            List<DtoLienPersonnes> lienPersonnes = input.getLienPersonnes();
            IEnvironnement environnement = new Environnement();
            if (CollectionUtils.isNotEmpty(lienPersonnes)) {
                List<ILien> liens = new ArrayList<ILien>(lienPersonnes.size());
                List<DtoPersonnePhysique> envPersPhysique = input.getEnvPersPhysique();
                List<DtoPersonneMorale> envPersMorale = input.getEnvPersMorale();
                List<DtoDossierCoordonneesBancaires> listeDossierCoordonneesBancaires =
                                input.getDossierCoordonneesBancaires();
                DtoDossierContact dossierContact = input.getDossierContact();
                List<DtoDossierSphereProfessionnelle> listDossierSpherePro = input.getDossierSphereProfessionnelle();
                String numeroClient = client.getNumeroClient();
                ILien lienCourant = null;
                for (int i = 0; i < lienPersonnes.size(); i++) {
                    lienCourant =
                                    mapperLien(lienPersonnes.get(i), envPersPhysique, envPersMorale, numeroClient,
                                                    listeDossierCoordonneesBancaires, dossierContact,
                                                    listDossierSpherePro);

                    if (lienCourant != null) {
                        liens.add(mapperLien(lienPersonnes.get(i), envPersPhysique, envPersMorale, numeroClient,
                                        listeDossierCoordonneesBancaires, dossierContact, listDossierSpherePro));
                    }
                }
                environnement.setLiens(liens);
            }
            client.setEnvironnement(environnement);

            ICharte charte = mapperCharte(input.getCharteAccompagnement());
            client.setCharte(charte);

            String loginEspaceClient = donneesContactP44Mapper.checkEspaceClient(client, input.getProfilMarketing());
            client.setCompteEspaceClient(loginEspaceClient);
            client.setEspaceClient(StringUtils.isEmpty(loginEspaceClient) ? false : true);

            if (input.getDossierDocument() != null) {
                List<IPieceIdentite> listePieceIdentite = mapperPieceIdentite(input.getDossierDocument());
                client.setListePieceIdentite(listePieceIdentite);
            }

        }

        return client;
    }

    /**
     * Détermine la nature de la personne
     * 
     * @param personneMorale la personne morale
     * @param personnePhysique la personne physique
     * @param isPersonnePhysique true si c'est une personne physique
     * @param isPersonneMorale true si c'est une personne morale
     * @return la nature de la personne
     */
    private NaturePersonne calculerNature(DtoPersonneMorale personneMorale, DtoPersonnePhysique personnePhysique,
                    boolean isPersonnePhysique, boolean isPersonneMorale) {
        NaturePersonne nature = NaturePersonne.PARTICULIER;
        if (isPersonnePhysique && personnePhysique.getParticulierProfessionnel() != null
                        && !personnePhysique.getParticulierProfessionnel().isEmpty()) {
            nature = NaturePersonne.PROFESSIONNEL;
        } else {
            if (isPersonneMorale) {
                nature = NaturePersonne.getNaturePersonneFromValue(personneMorale.getTypePersonneMorale());
            }
        }
        return nature;
    }

    /**
     * @param input un {@link DtoDossierP44}
     * @param nature la nature personne
     * @return une personne
     */
    private IPersonne buildClient(DtoDossierP44 input, NaturePersonne nature) {
        IPersonne client;
        switch (nature) {
            case PARTICULIER:
                client = dtoDossierP44ToClientParticulierConverter.convert(input);
                break;
            case PROFESSIONNEL:
                client = dtoDossierP44ToClientProfessionnelConverter.convert(input);
                break;
            case ASSOCIATION:
                client = dtoDossierP44ToClientAssociationConverter.convert(input);
                break;
            case COLLECTIVITE:
                client = dtoDossierP44ToClientCollectiviteConverter.convert(input);
                break;
            case COPROPRIETE:
                client = dtoDossierP44ToClientCoproprieteConverter.convert(input);
                break;
            case ENTREPRISE:
                client = dtoDossierP44ToClientEntrepriseConverter.convert(input);
                break;
            default:
                client = dtoDossierP44ToClientAutreConverter.convert(input);
                break;
        }
        return client;
    }

    /**
     * Mappe une personne physique
     * 
     * @param personnePhysique la personne physique
     * @param client la personne
     * @param listeDossierCoordonneesBancaires la liste des Coordonnees
     *            Bancaires
     * @param dossierContact le dossier contact
     * @param listDossierSpherePro la liste de dossier Sphere Pro
     * @param profilMarketing le profile marketing de la personne
     */
    private void mapperPersonnePhysique(DtoPersonnePhysique personnePhysique, IPersonne client,
                    List<DtoDossierCoordonneesBancaires> listeDossierCoordonneesBancaires,
                    DtoDossierContact dossierContact, List<DtoDossierSphereProfessionnelle> listDossierSpherePro,
                    DtoProfilMarketing profilMarketing, List<DtoDonneesMarketing> indicateurMarketing) {
        // Récupération des informations du niveau IPersonnePhysique
        IPersonnePhysique.class.cast(client).setPersonnePhysique(
                        dtoPersonnePhysique2PersonnePhysiqueP44Converter.convert(personnePhysique));

        // Récupération des informations du niveau IPersonne
        client.setNumeroClient(personnePhysique.getIdentifiantPersonne());

        // Indicateur client actif (true) ou désactivé (false)
        if (StringUtils.isEmpty(personnePhysique.getEtat()) || personnePhysique.getEtat().equals("0")) {
            client.setActif(true);
        } else {
            client.setActif(false);
        }

        buildVisibilitePP(client, personnePhysique);

        client.setTypeClient(personnePhysique.getStatutClient());

        if (personnePhysique.getDateCreation() != null) {
            client.setDateCreation(personnePhysique.getDateCreation().toGregorianCalendar().getTime());
        }

        if (personnePhysique.getDateDebutClient() != null) {
            client.setDateDebut(personnePhysique.getDateDebutClient().toGregorianCalendar().getTime());
            client.setDatePassageClient(personnePhysique.getDateDebutClient().toGregorianCalendar().getTime());
        }

        if (personnePhysique.getDateFinClient() != null) {
            client.setDateFinClient(personnePhysique.getDateFinClient().toGregorianCalendar().getTime());
        }

        if (personnePhysique.getDateDerniereMiseAJour() != null) {
            client.setDateDernierMaj(personnePhysique.getDateDerniereMiseAJour().toGregorianCalendar().getTime());
        }

        client.setIdClientFue(personnePhysique.getDenominationFUE());
        
        if (indicateurMarketing != null) {
	        // Lecture des donnees marketing
	        client.setDonneeMarketing(mapperDonneesMarketing(indicateurMarketing));
        }

        buildCoordonneesBancaires(client, listeDossierCoordonneesBancaires);
        buildCoordonneesContactPP(client, dossierContact, listDossierSpherePro, profilMarketing);
        buildIndicateursDemat(client, personnePhysique);
    }

	/**
     * mappe la visibilité client
     * 
     * @param personnePhysique la personne physique
     * @param client la personne
     */
    private void buildVisibilitePP(IPersonne client, DtoPersonnePhysique personnePhysique) {
        if (personnePhysique.getVisibilite() != null) {
            if (StringUtils.isNotEmpty(personnePhysique.getVisibilite().getIdentifiantClientAgent())) {
                client.setNumeroClientAgent(personnePhysique.getVisibilite().getIdentifiantClientAgent());
            }
            client.setCodeIntermediaire(personnePhysique.getVisibilite().getIdentifiantIntermediaire());

            if (StringUtils.isNotEmpty(personnePhysique.getVisibilite().getIdentifiantChargeClientele())) {
                client.setChargeClientele(personnePhysique.getVisibilite().getIdentifiantChargeClientele());
            }

            if (StringUtils.isNotEmpty(personnePhysique.getVisibilite().getIdentifiantPointVente())) {
                client.setPointDeVente(personnePhysique.getVisibilite().getIdentifiantPointVente());
            }
        }
    }

    /**
     * Mappe une personne morale
     * 
     * @param personneMorale la personne morale
     * @param client la personne
     * @param listeDossierCoordonneesBancaires la liste des Coordonnees
     *            Bancaires
     * @param dossierContact le dossier contact
     * @param profilMarketing le profile marketing de la personne
     */
    private void mapperPersonneMorale(DtoPersonneMorale personneMorale, IPersonne client,
                    List<DtoDossierCoordonneesBancaires> listeDossierCoordonneesBancaires,
                    DtoDossierContact dossierContact, DtoProfilMarketing profilMarketing) {
        // Récupération des informations du niveau IPersonneMorale
        IPersonneMorale.class.cast(client).setPersonneMorale(
                        dtoPersonneMorale2PersonneMoraleP44Converter.convert(personneMorale));

        // Récupération des informations du niveau IPersonne
        client.setNumeroClient(personneMorale.getIdentifiantPersonne());

        // Indicateur client actif (true) ou désactivé (false)
        if (StringUtils.isEmpty(personneMorale.getEtat()) || personneMorale.getEtat().equals("0")) {
            client.setActif(true);
        } else {
            client.setActif(false);
        }

        buildVisibilitePM(client, personneMorale);

        client.setTypeClient(personneMorale.getStatutClient());

        if (personneMorale.getDateCreation() != null) {
            client.setDateCreation(personneMorale.getDateCreation().toGregorianCalendar().getTime());
        }

        if (personneMorale.getDateDebutClient() != null) {
            client.setDateDebut(personneMorale.getDateDebutClient().toGregorianCalendar().getTime());
            client.setDatePassageClient(personneMorale.getDateDebutClient().toGregorianCalendar().getTime());
        }

        if (personneMorale.getDateFinClient() != null) {
            client.setDateFinClient(personneMorale.getDateFinClient().toGregorianCalendar().getTime());
        }

        if (personneMorale.getDateDerniereMiseAJour() != null) {
            client.setDateDernierMaj(personneMorale.getDateDerniereMiseAJour().toGregorianCalendar().getTime());
        }

        client.setIdClientFue(personneMorale.getDenominationFUE());

        buildCoordonneesBancaires(client, listeDossierCoordonneesBancaires);
        buildCoordonneesContactPM(client, dossierContact, profilMarketing);
        buildIndicateursDemat(client, personneMorale);
    }

    /**
     * mappe la visibilité client
     * 
     * @param personneMorale la personne morale
     * @param client la personne
     */
    private void buildVisibilitePM(IPersonne client, DtoPersonneMorale personneMorale) {
        if (personneMorale.getVisibilite() != null) {
            if (StringUtils.isNotEmpty(personneMorale.getVisibilite().getIdentifiantClientAgent())) {
                client.setNumeroClientAgent(personneMorale.getVisibilite().getIdentifiantClientAgent());
            }
            client.setCodeIntermediaire(personneMorale.getVisibilite().getIdentifiantIntermediaire());

            if (StringUtils.isNotEmpty(personneMorale.getVisibilite().getIdentifiantChargeClientele())) {
                client.setChargeClientele(personneMorale.getVisibilite().getIdentifiantChargeClientele());
            }

            if (StringUtils.isNotEmpty(personneMorale.getVisibilite().getIdentifiantPointVente())) {
                client.setPointDeVente(personneMorale.getVisibilite().getIdentifiantPointVente());
            }
        }
    }

    /**
     * Mappe un lien
     * 
     * @param dtoLienPersonnes le lien
     * @param envPersPhysique les personnes physiques de l'environnement
     * @param envPersMorale les personnes morales de l'environnement
     * @param numeroClient l'id de la personne
     * @param listeDossierCoordonneesBancaires la liste des Coordonnees
     *            Bancaires
     * @param dossierContact le dossier contact
     * @param listDossierSpherePro la liste de dossier Sphere Pro
     * @return un lien
     */
    private ILien mapperLien(DtoLienPersonnes dtoLienPersonnes, List<DtoPersonnePhysique> envPersPhysique,
                    List<DtoPersonneMorale> envPersMorale, String numeroClient,
                    List<DtoDossierCoordonneesBancaires> listeDossierCoordonneesBancaires,
                    DtoDossierContact dossierContact, List<DtoDossierSphereProfessionnelle> listDossierSpherePro) {
        String idPersonneLiee = null;
        ILien lien = new Lien();

        if (dtoLienPersonnes != null && dtoLienPersonnes.getRole1() != null) {
            lien.setRole1(dtoLienPersonnes.getRole1().getTypeRoleDansLienPersonne());

            if (!numeroClient.equals(dtoLienPersonnes.getRole1().getPersonneLiee())) {
                idPersonneLiee = dtoLienPersonnes.getRole1().getPersonneLiee();
            }
        }

        if (dtoLienPersonnes != null && dtoLienPersonnes.getRole2() != null) {
            lien.setRole2(dtoLienPersonnes.getRole2().getTypeRoleDansLienPersonne());

            if (!numeroClient.equals(dtoLienPersonnes.getRole2().getPersonneLiee())) {
                idPersonneLiee = dtoLienPersonnes.getRole2().getPersonneLiee();
            }
        }

        if (idPersonneLiee == null) {
            return null;
        } else {
            lien =
                            valideLien(lien, envPersPhysique, envPersMorale, idPersonneLiee,
                                            listeDossierCoordonneesBancaires, dossierContact, listDossierSpherePro);
        }

        return lien;
    }

    /**
     * Vérifie le lien
     * 
     * @param lien le lien à valider
     * @param envPersPhysique les personnes physiques de l'environnement
     * @param envPersMorale les personnes morales de l'environnement
     * @param idPersonneLiee l'id de la personne liée
     * @param listeDossierCoordonneesBancaires la liste des Coordonnees
     *            Bancaires
     * @param dossierContact le dossier contact
     * @param listDossierSpherePro la liste de dossier Sphere Pro
     * @return un lien
     */
    private ILien valideLien(ILien lien, List<DtoPersonnePhysique> envPersPhysique,
                    List<DtoPersonneMorale> envPersMorale, String idPersonneLiee,
                    List<DtoDossierCoordonneesBancaires> listeDossierCoordonneesBancaires,
                    DtoDossierContact dossierContact, List<DtoDossierSphereProfessionnelle> listDossierSpherePro) {
        if (envPersPhysique != null) {
            DtoPersonnePhysique dtoPersonnePhysique = null;
            for (int i = 0; i < envPersPhysique.size(); i++) {
                dtoPersonnePhysique = envPersPhysique.get(i);
                if (idPersonneLiee.equals(dtoPersonnePhysique.getIdentifiantPersonne())) {
                    NaturePersonne nature = calculerNature(null, dtoPersonnePhysique, true, false);
                    DtoDossierP44 dtoDossierP44 = new DtoDossierP44();
                    dtoDossierP44.setPersonnePhysique(dtoPersonnePhysique);
                    IPersonne personne = buildClient(dtoDossierP44, nature);
                    mapperPersonnePhysique(dtoPersonnePhysique, personne, listeDossierCoordonneesBancaires,
                                    dossierContact, listDossierSpherePro, null, null);
                    lien.setPersonneLiee(personne);
                    break;
                }
            }
        }

        if (envPersMorale != null) {
            DtoPersonneMorale dtoPersonneMorale = null;
            for (int i = 0; i < envPersMorale.size(); i++) {
                dtoPersonneMorale = envPersMorale.get(i);
                if (idPersonneLiee.equals(dtoPersonneMorale.getIdentifiantPersonne())) {
                    // TODO : Remplacer la valeur en dur par le commentaire
                    // quand suppression BCC
                    // NaturePersonne nature = calculerNature(dtoPersonneMorale,
                    // null, false, true);
                    NaturePersonne nature = NaturePersonne.ENTREPRISE;
                    DtoDossierP44 dtoDossierP44 = new DtoDossierP44();
                    dtoDossierP44.setPersonneMorale(dtoPersonneMorale);
                    IPersonne personne = buildClient(dtoDossierP44, nature);
                    mapperPersonneMorale(dtoPersonneMorale, personne, listeDossierCoordonneesBancaires, dossierContact,
                                    null);
                    lien.setPersonneLiee(personne);
                    break;
                }
            }
        }

        return lien;
    }

    /**
     * @param listeDtoCharteAccompagnement la liste des Charte Accompagnement
     * @return la charte
     */
    private ICharte mapperCharte(List<DtoCharteAccompagnement> listeDtoCharteAccompagnement) {
        LOGGER.info("mapperCharte");
        ICharte charte = null;

        for (DtoCharteAccompagnement dtoCharte : listeDtoCharteAccompagnement) {
            LOGGER.debug("Taille listeCharteAccompagnement : " + listeDtoCharteAccompagnement.size());
            charte = dtoCharteAccompagnement2CharteConverter.convert(dtoCharte);
            break;
        }

        return charte;
    }

    /**
     * @param dossierDocument la liste des piece d'identité
     * @return la liste des piece d'identité
     */
    private List<IPieceIdentite> mapperPieceIdentite(DtoDossierDocument dossierDocument) {
        LOGGER.info("mapperPieceIdentite");
        List<DtoPieceIdentite> listeDtoPieceIdentite = dossierDocument.getPieceIdentite();
        DtoIdentifiantSecuriteSociale idSecuriteSociale = dossierDocument.getIdentifiantSecuriteSociale();
        List<IPieceIdentite> listePieceIdentite = new ArrayList<IPieceIdentite>();

        if (idSecuriteSociale != null) {
            IPieceIdentite pieceIdentite = new PieceIdentite();
            pieceIdentite.setNumero(idSecuriteSociale.getNumeroSS());
            pieceIdentite.setType("04");
            if (idSecuriteSociale.getDateValidite() != null && idSecuriteSociale.getDateValidite().getEndDate() != null) {
                pieceIdentite.setDateFinValidite(idSecuriteSociale.getDateValidite().getEndDate().toGregorianCalendar()
                                .getTime());
            }
            listePieceIdentite.add(pieceIdentite);
        }

        for (DtoPieceIdentite dtoPieceIdentite : listeDtoPieceIdentite) {
            listePieceIdentite.add(dtoPieceIdentite2PieceIdentiteConverter.convert(dtoPieceIdentite));
        }

        return listePieceIdentite;
    }

    /**
     * Construit les coordonnées bancaires du client
     * 
     * @param client le client
     * @param listeDossierCoordonneesBancaires ses coordonnées bancaires
     */
    private void buildCoordonneesBancaires(IPersonne client,
                    List<DtoDossierCoordonneesBancaires> listeDossierCoordonneesBancaires) {
        client.setListeCoordonneesBancaires(dtoDossierCoordonneesBancaires2ListCoordonneeBancaireP44Converter
                        .convert(listeDossierCoordonneesBancaires));
        if (client.getListeCoordonneesBancaires() != null && !client.getListeCoordonneesBancaires().isEmpty()) {
            client.setCoordonneeBancaire(client.getListeCoordonneesBancaires().get(0));
        }
    }

    /**
     * Construit les coordonnées de contact du client
     * 
     * @param client le client
     * @param dossierContact ses coordonnées
     * @param listDossierSpherePro la sphere pour le Pro
     * @param profilMarketing le profile marketing de la personne
     */
    private void buildCoordonneesContactPP(IPersonne client, DtoDossierContact dossierContact,
                    List<DtoDossierSphereProfessionnelle> listDossierSpherePro, DtoProfilMarketing profilMarketing) {
        if (dossierContact != null) {
            buildAdresses(client, dossierContact, profilMarketing);
            buildTelephones(client, dossierContact);
            buildEmails(client, dossierContact);
            buildSiteInternets(client, dossierContact);
            buildCommunicationClient(client, dossierContact);
        }

        if (CollectionUtils.isNotEmpty(listDossierSpherePro)) {
            DtoDossierSphereProfessionnelle dossierSpherePro = listDossierSpherePro.get(0);
            completeTelephonesPro(client, dossierSpherePro);
            completeEmailsPro(client, dossierSpherePro);
            completeSiteInternetsPro(client, dossierSpherePro);
        }
    }

    /**
     * Construit les coordonnées de contact du client
     * 
     * @param client le client
     * @param dossierContact ses coordonnées
     * @param profilMarketing le profile marketing de la personne
     */
    private void buildCoordonneesContactPM(IPersonne client, DtoDossierContact dossierContact,
                    DtoProfilMarketing profilMarketing) {
        if (dossierContact != null) {
            buildAdresses(client, dossierContact, profilMarketing);
            buildTelephones(client, dossierContact);
            buildEmails(client, dossierContact);
            buildSiteInternets(client, dossierContact);
            buildCommunicationClient(client, dossierContact);
        }
    }

    /**
     * Construit les coordonnées de type adresse du client
     * 
     * @param client le client
     * @param dossierContact ses coordonnées
     * @param profilMarketing le profile marketing de la personne
     */
    private void buildAdresses(IPersonne client, DtoDossierContact dossierContact, DtoProfilMarketing profilMarketing) {
        if (dossierContact != null) {
            client.setAdressePrincipale(donneesContactP44Mapper.getAdressePrincipale(
                            dossierContact.getAdressePrincipale(), profilMarketing));

            List<IAdresse> listeAdresses = new ArrayList<IAdresse>();
            listeAdresses =
                            donneesContactP44Mapper.getListeAdressePrincipale(dossierContact.getAdressePrincipale(),
                                            listeAdresses, profilMarketing);
            listeAdresses =
                            donneesContactP44Mapper.getListeAdresseCourrier(dossierContact.getAdresseCourrier(),
                                            listeAdresses, profilMarketing);
            listeAdresses =
                            donneesContactP44Mapper.getListeAdresseFiscale(dossierContact.getAdresseFiscale(),
                                            listeAdresses, profilMarketing);
            listeAdresses =
                            donneesContactP44Mapper.getListeAdresseSecondaire(dossierContact.getAdresseSecondaire(),
                                            listeAdresses, profilMarketing);
            client.setListeAdresse(listeAdresses);
        }
    }

    /**
     * Construit les coordonnées de type telephone du client
     * 
     * @param client le client
     * @param dossierContact ses coordonnées
     */
    private void buildTelephones(IPersonne client, DtoDossierContact dossierContact) {
        if (dossierContact != null) {
            List<ITelephone> listeTelephones = new ArrayList<ITelephone>();
            listeTelephones =
                            donneesContactP44Mapper.getListeTelephone(dossierContact.getTelephonePrincipal(),
                                            listeTelephones, true);
            listeTelephones =
                            donneesContactP44Mapper.getListeTelephone(dossierContact.getTelephoneSecondaire(),
                                            listeTelephones, false);
            client.setListeTelephone(listeTelephones);
        }
    }

    /**
     * Construit les coordonnées de type email du client
     * 
     * @param client le client
     * @param dossierContact ses coordonnées
     */
    private void buildEmails(IPersonne client, DtoDossierContact dossierContact) {
        if (dossierContact != null) {
            client.setEmail(donneesContactP44Mapper.getEmail(dossierContact.getCourrielPrincipal()));

            List<IEmail> listeEmails = new ArrayList<IEmail>();
            listeEmails =
                            donneesContactP44Mapper.getListeEmail(dossierContact.getCourrielPrincipal(), listeEmails,
                                            true);
            listeEmails =
                            donneesContactP44Mapper.getListeEmail(dossierContact.getCourrielSecondaire(), listeEmails,
                                            false);
            client.setListeEmail(listeEmails);

            if (client.getEmail() == null && CollectionUtils.isNotEmpty(listeEmails)) {
                client.setEmail(listeEmails.get(0));
            }
        }
    }

    /**
     * Construit les coordonnées de type site internet du client
     * 
     * @param client le client
     * @param dossierContact ses coordonnées
     */
    private void buildSiteInternets(IPersonne client, DtoDossierContact dossierContact) {
        if (dossierContact != null) {
            List<ISiteInternet> listeSiteInternets = new ArrayList<ISiteInternet>();
            listeSiteInternets =
                            donneesContactP44Mapper.getListeSiteInternet(dossierContact.getPageWebPrincipale(),
                                            listeSiteInternets, true);
            listeSiteInternets =
                            donneesContactP44Mapper.getListeSiteInternet(dossierContact.getPageWebSecondaire(),
                                            listeSiteInternets, false);
            client.setListeSiteInternet(listeSiteInternets);
        }
    }

    /**
     * Construit les coordonnées de type communication du client
     * 
     * @param client le client
     * @param dossierContact ses coordonnées
     */
    private void buildCommunicationClient(IPersonne client, DtoDossierContact dossierContact) {
        if (dossierContact == null || CollectionUtils.isEmpty(dossierContact.getStopCom())) {
            Communication communication = new Communication();
            communication.setEmailOk(true);
            communication.setCourrierOk(true);
            communication.setAutorisation(false);
            communication.setSmsOk(true);
            communication.setTelephoneOk(true);
            communication.setCanalDePreference(null);

            client.setCommunication(communication);
        } else {
            client.setCommunication(chargerCommunication(dossierContact));
        }
    }

    /**
     * Complete les coordonnées de type telephone du client professionnel
     * 
     * @param dossierContact les coordonnées du client
     * @return communication
     */
    private Communication chargerCommunication(DtoDossierContact dossierContact) {
        // Chargement des stopComs
        DtoInformationCommunication dtoInformationCommunication = dossierContact.getStopCom().get(0);
        Communication communication = new Communication();
        communication.setCanalDePreference(dossierContact.getCodeCanalPrefere());
        communication.setAutorisation((dossierContact.getDemarchage() == null || dossierContact.getDemarchage()
                        .isIndicateurAutorisationInformation() == null) ? false : dossierContact.getDemarchage()
                        .isIndicateurAutorisationInformation());

        if (dtoInformationCommunication == null) {
            communication.setEmailOk(true);
            communication.setCourrierOk(true);
            communication.setSmsOk(true);
            communication.setTelephoneOk(true);
        } else {
            communication.setEmailOk(dtoInformationCommunication.isIndicateurStopCourriel() == null ? true
                            : !dtoInformationCommunication.isIndicateurStopCourriel());
            communication.setCourrierOk(dtoInformationCommunication.isIndicateurStopCourrier() == null ? true
                            : !dtoInformationCommunication.isIndicateurStopCourrier());
            communication.setSmsOk(dtoInformationCommunication.isIndicateurStopSMS() == null ? true
                            : !dtoInformationCommunication.isIndicateurStopSMS());
            communication.setTelephoneOk(dtoInformationCommunication.isIndicateurStopTelephone() == null ? true
                            : !dtoInformationCommunication.isIndicateurStopTelephone());
        }

        return communication;
    }

    /**
     * Complete les coordonnées de type telephone du client professionnel
     * 
     * @param client le client
     * @param dossierSpherePro ses coordonnées professionnelles
     */
    private void completeTelephonesPro(IPersonne client, DtoDossierSphereProfessionnelle dossierSpherePro) {
        if (dossierSpherePro != null && dossierSpherePro.getDossierContactSpherePro() != null) {
            DtoDossierContact dossierContactPro = dossierSpherePro.getDossierContactSpherePro();
            List<ITelephone> listeTelephones = new ArrayList<ITelephone>();

            listeTelephones =
                            donneesContactP44Mapper.getListeTelephone(dossierContactPro.getTelephonePrincipal(),
                                            listeTelephones, true);
            listeTelephones =
                            donneesContactP44Mapper.getListeTelephone(dossierContactPro.getTelephoneSecondaire(),
                                            listeTelephones, false);

            if (CollectionUtils.isNotEmpty(client.getListeTelephone())) {
                client.getListeTelephone().addAll(listeTelephones);
            } else {
                client.setListeTelephone(listeTelephones);
            }
        }
    }

    /**
     * Complete les coordonnées de type email du client professionnel
     * 
     * @param client le client
     * @param dossierSpherePro ses coordonnées professionnelles
     */
    private void completeEmailsPro(IPersonne client, DtoDossierSphereProfessionnelle dossierSpherePro) {
        if (dossierSpherePro != null && dossierSpherePro.getDossierContactSpherePro() != null) {
            DtoDossierContact dossierContactPro = dossierSpherePro.getDossierContactSpherePro();

            client.setEmail(donneesContactP44Mapper.getEmail(dossierContactPro.getCourrielPrincipal()));

            List<IEmail> listeEmails = new ArrayList<IEmail>();
            listeEmails =
                            donneesContactP44Mapper.getListeEmail(dossierContactPro.getCourrielPrincipal(),
                                            listeEmails, true);
            listeEmails =
                            donneesContactP44Mapper.getListeEmail(dossierContactPro.getCourrielSecondaire(),
                                            listeEmails, false);

            if (CollectionUtils.isNotEmpty(client.getListeEmail())) {
                client.getListeEmail().addAll(listeEmails);
            } else {
                client.setListeEmail(listeEmails);
            }

            if (client.getEmail() == null && CollectionUtils.isNotEmpty(client.getListeEmail())) {
                client.setEmail(client.getListeEmail().get(0));
            }
        }
    }

    /**
     * Complete les coordonnées de type site internet du client professionnel
     * 
     * @param client le client
     * @param dossierSpherePro ses coordonnées professionnelles
     */
    private void completeSiteInternetsPro(IPersonne client, DtoDossierSphereProfessionnelle dossierSpherePro) {
        if (dossierSpherePro != null && dossierSpherePro.getDossierContactSpherePro() != null) {
            DtoDossierContact dossierContactPro = dossierSpherePro.getDossierContactSpherePro();

            List<ISiteInternet> listeSiteInternets = new ArrayList<ISiteInternet>();
            listeSiteInternets =
                            donneesContactP44Mapper.getListeSiteInternet(dossierContactPro.getPageWebPrincipale(),
                                            listeSiteInternets, true);
            listeSiteInternets =
                            donneesContactP44Mapper.getListeSiteInternet(dossierContactPro.getPageWebSecondaire(),
                                            listeSiteInternets, false);

            if (CollectionUtils.isNotEmpty(client.getListeSiteInternet())) {
                client.getListeSiteInternet().addAll(listeSiteInternets);
            } else {
                client.setListeSiteInternet(listeSiteInternets);
            }
        }
    }

    /**
     * @param client client d'appel
     * @param dtoPersonne dto personne cote RCE
     */
    private void buildIndicateursDemat(IPersonne client, AbstractDtoPersonne dtoPersonne) {

        client.setIndicateursDemat(dtoIndicateurDematerialisation2IndicateurDematP44Converter.convert(dtoPersonne
                        .getInformationDematerialisation()));
    }
    
    /**
     * @param listeDtoDonneesMarketing la liste de données marketing renvoyée
     *            par le WS
     * @return la donnée marketing {@link IDonneeMarketing}
     */
    private IDonneeMarketing mapperDonneesMarketing(List<DtoDonneesMarketing> listeDtoDonneesMarketing) {
        LOGGER.info("mapperDonneesMarketing");

        return dtoDonneesMarketing2DonneeMarketingConverter.convert(listeDtoDonneesMarketing);
    }
}
